package cn.jacksigxu.min3halla.datagen;

import cn.jacksigxu.min3halla.block.IngredientCanBlock;
import cn.jacksigxu.min3halla.block.drink.SizedDrinkBlock;
import cn.jacksigxu.min3halla.init.MHBlocks;
import cn.jacksigxu.min3halla.loot.SetAlcoholNbtFunction;
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.data.loot.BlockLootSubProvider;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.entries.LootItem;
import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction;
import net.minecraft.world.level.storage.loot.functions.SetNbtFunction;
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraftforge.registries.RegistryObject;

import java.util.List;
import java.util.Set;

public class ModBlockLootProvider extends BlockLootSubProvider {

    public ModBlockLootProvider() {
        super(Set.of(), FeatureFlags.REGISTRY.allFlags());
    }

    @Override
    protected void generate() {
        this.dropSelf(MHBlocks.DRINK_MIXER.get());
        this.dropSelf(MHBlocks.FERMENT_BARREL.get());
        this.dropSelf(MHBlocks.BTC_FILLING_MACHINE.get());

        this.ingredientBlock(MHBlocks.BTC_CAN_BLOCK.get());
        this.ingredientBlock(MHBlocks.ADELHYDE_BLOCK.get());
        this.ingredientBlock(MHBlocks.BRONSON_EXTRACT_BLOCK.get());
        this.ingredientBlock(MHBlocks.FLANERGIDE_BLOCK.get());
        this.ingredientBlock(MHBlocks.KARMOTRINE_BLOCK.get());
        this.ingredientBlock(MHBlocks.POWDERED_DELTA_BLOCK.get());
        this.ingredientBlock(MHBlocks.HYPER_ACID_X_BLOCK.get());
        this.ingredientBlock(MHBlocks.GLITCH_LIQUID_BLOCK.get());

        this.dropSelf(MHBlocks.FRIED_RICE_BLOCK.get());

        this.sizedDrink(MHBlocks.BAD_TOUCH_BLOCK.get());
        this.sizedDrink(MHBlocks.BEER_BLOCK.get());
        this.sizedDrink(MHBlocks.BLEEDING_JANE_BLOCK.get());
        this.sizedDrink(MHBlocks.BLOOM_LIGHT_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.BLUE_FAIRY_BLOCK.get());
        this.sizedDrink(MHBlocks.BRANDTINI_BLOCK.get());
        this.sizedDrink(MHBlocks.COBALT_VELVET_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.CREVICE_SPIKE_BLOCK.get());
        this.dropSelf(MHBlocks.FLAMING_MOAI_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.FLUFFY_DREAM_BLOCK.get());
        this.sizedDrink(MHBlocks.FRINGE_WEAVER_BLOCK.get());
        this.sizedDrink(MHBlocks.FROTHY_WATER_BLOCK.get());
        this.sizedDrink(MHBlocks.GRIZZLY_TEMPLE_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.GUT_PUNCH_BLOCK.get());
        this.dropSelf(MHBlocks.MARSBLAST_BLOCK.get());
        this.sizedDrink(MHBlocks.MERCURYBLAST_BLOCK.get());
        this.sizedDrink(MHBlocks.MOONBLAST_BLOCK.get());
        this.dropSelf(MHBlocks.PIANO_MAN_BLOCK.get());
        this.dropSelf(MHBlocks.PIANO_WOMAN_BLOCK.get());
        this.sizedDrink(MHBlocks.PILE_DRIVER_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.SPARKLE_STAR_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.SUGAR_RUSH_BLOCK.get());
        this.mutableAlcoholDrink(MHBlocks.SUNSHINE_CLOUD_BLOCK.get());
        this.sizedDrink(MHBlocks.SUPLEX_BLOCK.get());
        this.dropSelf(MHBlocks.ZEN_STAR_BLOCK.get());

        this.dropSelf(MHBlocks.MULAN_TEA_BLOCK.get());
        this.dropSelf(MHBlocks.A_FEDORA_BLOCK.get());
        this.dropSelf(MHBlocks.RUM_BLOCK.get());
        this.dropSelf(MHBlocks.ABSINTHE_BLOCK.get());

        this.sizedDrink(MHBlocks.SEPTWOLVES_BLOCK.get());
        this.dropSelf(MHBlocks.ALARM_LAMP_BLOCK.get());
        this.dropSelf(MHBlocks.SUPERB_BASKETBALL_BLOCK.get());
        this.dropSelf(MHBlocks.FOX_WINE_BLOCK.get());

        this.dropSelf(MHBlocks.ERROR_DRINK_BLOCK.get());
    }

    public void ingredientBlock(Block block) {
        this.add(block, b -> LootTable.lootTable().withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(1.0F))
                        .add(this.applyExplosionDecay(block, LootItem.lootTableItem(b).apply(List.of(2, 3, 4),
                                count -> SetItemCountFunction.setCount(ConstantValue.exactly((float) count))
                                        .when(LootItemBlockStatePropertyCondition.hasBlockStateProperties(b).setProperties(StatePropertiesPredicate.Builder.properties().hasProperty(IngredientCanBlock.COUNT, count))))))
                )
        );
    }

    public void sizedDrink(Block block) {
        var condition = LootItemBlockStatePropertyCondition.hasBlockStateProperties(block)
                .setProperties(StatePropertiesPredicate.Builder.properties().hasProperty(SizedDrinkBlock.DOUBLE_INGREDIENTS, true));
        var tag = new CompoundTag();
        tag.putBoolean("Big", true);
        this.add(block, this.applyExplosionDecay(block,
                LootTable.lootTable().withPool(
                        LootPool.lootPool().add(LootItem.lootTableItem(block).apply(SetNbtFunction.setTag(tag)).when(condition)
                                .otherwise(LootItem.lootTableItem(block)))))
        );
    }

    public void mutableAlcoholDrink(Block block) {
        var big = LootItemBlockStatePropertyCondition.hasBlockStateProperties(block)
                .setProperties(StatePropertiesPredicate.Builder.properties().hasProperty(SizedDrinkBlock.DOUBLE_INGREDIENTS, true));
        var tag = new CompoundTag();
        tag.putBoolean("Big", true);
        this.add(block, this.applyExplosionDecay(block, LootTable.lootTable().withPool(
                                LootPool.lootPool().add(
                                        LootItem.lootTableItem(block).apply(SetNbtFunction.setTag(tag)).apply(SetAlcoholNbtFunction.of()).when(big)
                                                .otherwise(LootItem.lootTableItem(block).apply(SetAlcoholNbtFunction.of()))
                                )
                        )
                )
        );
    }

    @Override
    protected Iterable<Block> getKnownBlocks() {
        return MHBlocks.BLOCKS.getEntries().stream().map(RegistryObject::get)::iterator;
    }
}
